#ifndef BYTE_CODE_H
#define BYTE_CODE_H
#include "common.h"

#ifdef TAG
#undef TAG
#endif
#define TAG "INTERPRETER "

const string MOV_CON_NAME = "MOV_CON";
const string MOV_NAME = "MOV";
const string ADD_NAME = "ADD";
const string MINUS_NAME = "MINUS";
const string MUL_NAME = "MUL";
const string DIV_NAME = "DIV";
const string UNKNOWN_NAME = "UNKNOWN";
const string PRINT_NAME = "PRINT";

enum class BYTE_CODE : int
{
    UNKNOWN =  0,
    MOV_CON,      // MOV_CON Rn val (move const value to register n)
    MOV,         // MOV Rm Rn (move value in register n to register m)
    ADD,         // ADD Rm Rn (add value in register m and register n, put result in register m)
    MINUS,       // MINUS Rm Rn (value in register m minus value in register n, put result in register m)
    MUL,         // MUL Rm Rn (value in register m multiply value register n, put result in register m)
    DIV,         // DIV Rm Rn (value in register m divide value in register n, put result in register m)
    PRINT,       // PRINT Rm x (print val int register m)
};

class ByteCodeHelper
{
public:
    static string GetNameByByteCode(BYTE_CODE code);
    static BYTE_CODE GetByteCodeByName(string name);
};

class ByteCode
{
public:
    ByteCode() : byte_code_(BYTE_CODE::UNKNOWN), source_(-1), target_(-1) {};
    ByteCode(BYTE_CODE byte_code, int target, int source = -1) : byte_code_(byte_code), target_(target), source_(source) {};
    virtual ~ByteCode() = default;
    string GetCode();

private:
    int target_;
    int source_;
    BYTE_CODE byte_code_;
};
#endif // BYTE_CODE_H